[自然言語処理/NLP] Word2VecをSageMaker上で使ってみる (実行編)
こんにちは、Mr.Moです。 Word2Vecについて理論を学んだので、次は実際に使ってみたいと思います。
ちなみに理論については下記の記事にまとめました。
前提
この記事ではSageMaker上で動かすことを前提に進めていきます。 SageMakerについては弊社ブログで情報を発信しておりますのでこちらも参考にしてみてください。 https://dev.classmethod.jp/referencecat/amazon-sagemaker/
事前準備
SageMakerでノートブックインスタンスの作成
まずはじめにSageMakerの画面を開きます。
次にノートプックインスタンスを作成します。 下記の要領で赤枠の部分を対応して後はデフォルトのままで大丈夫です。
ノートブックはconda_python3の環境で実行します。
MeCabのインストール
ノートブックのセルに下記のコードをコピペしておもむろに実行してください。完了まで少し時間がかかります。
参考:https://qiita.com/YuukiMiyoshi/items/00b9878a1fa32b859a43
%%bash sudo yum install -y bzip2 bzip2-devel gcc gcc-c++ git make wget curl openssl-devel readline-devel zlib-devel patch file # 作業フォルダを作成して移動 mkdir -p ~/source/mecab cd ~/source/mecab # ソースをダウンロードして解凍して移動 wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE' -O mecab-0.996.tar.gz tar zxvf mecab-0.996.tar.gz cd mecab-0.996 # インストール先フォルダを作成 sudo mkdir -p /opt/mecab # configure(コンパイルのための設定)を実行し、コンパイルしてインストール ./configure --prefix=/opt/mecab --with-charset=utf8 --enable-utf8-only make sudo make install # bashの場合 echo "export PATH=/opt/mecab/bin:\$PATH" >> ~/.bashrc source ~/.bashrc sudo bash -c "echo \"/opt/mecab/lib\" > /etc/ld.so.conf.d/libmecab.conf" sudo ldconfig # 作業フォルダを作成して移動 mkdir ~/source/mecab-ipadic cd ~/source/mecab-ipadic # 辞書ファイルを取得して解凍して移動 wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM' -O mecab-ipadic-2.7.0-20070801.tar.gz tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz cd mecab-ipadic-2.7.0-20070801 # 設定してmakeしてインストール ./configure --with-mecab-config=/opt/mecab/bin/mecab-config --with-charset=utf8 make sudo make install # 作業フォルダに移動してファイルを取得 cd ~/source git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git # 設定とともにインストールを実行 ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y -p /opt/mecab/lib/mecab/dic/neologd
Word2Vecの学習済みモデルダウンロード
今回は学習済みのモデルを使わせていただきましょう。 ノートブックのセルに下記のコードをコピペして実行します。
参考:http://aial.shiroyagi.co.jp/2017/02/japanese-word2vec-model-builder/
!wget http://public.shiroyagi.s3.amazonaws.com/latest-ja-word2vec-gensim-model.zip !unzip latest-ja-word2vec-gensim-model.zip
各種モジュールのインストール
こちらも同様にコードをノートブックのセルにコピペして実行してください。
!pip install --upgrade pip !pip install gensim !pip uninstall numpy -y !pip install numpy !pip install mecab-python3
モデルの読み込み
同様。
from gensim.models.word2vec import Word2Vec import gensim model_path = './word2vec.gensim.model' model_w2v = Word2Vec.load(model_path)
Word2Vec使ってみる
準備が整ったのでさっそく試していきましょう。
単語の演算
下記は 王様 - 男 + 女
の計算です。ちゃんとそれっぽい結果になっているのが面白いですね。
model_w2v.wv.most_similar(positive=['王様','女'], negative=['男'], topn=5)
文章の類似を判定してみよう
Word2Vecは基本的に単語単位での処理を行いますが、実際は文章単位で扱いたくなりますよね。 下記の記事を参考にちょっとやってみましょう
参考:https://qiita.com/yoppe/items/512c7c072d08c64afa7e
下準備
必要な処理を関数に定義しておきます。 下記、関数のコードもノートブックのセルにコピペして実行しておいてください。
- 分かち書き用関数
import MeCab mecab = MeCab.Tagger("-Owakati -d /opt/mecab/lib/mecab/dic/neologd") def get_wakati(sentence): return mecab.parse(sentence).replace(' \n', '').split()
- 類似度算出用関数
import numpy as np def avg_feature_vector(sentence, num_features): words = get_wakati(sentence) feature_vec = np.zeros((num_features,), dtype="float32") # 特徴ベクトルの入れ物を初期化 print(words) for word in words: feature_vec = np.add(feature_vec, model_w2v.wv[word]) if len(words) > 0: feature_vec = np.divide(feature_vec, len(words)) return feature_vec
from scipy import spatial def sentence_similarity_w2v(sentence_1, sentence_2): num_features=50 sentence_1_avg_vector = avg_feature_vector(sentence_1, num_features) sentence_2_avg_vector = avg_feature_vector(sentence_2, num_features) # 1からベクトル間の距離を引いてあげることで、コサイン類似度を計算 return 1 - spatial.distance.cosine(sentence_1_avg_vector, sentence_2_avg_vector)
文章の類似度を見てみる
だいたい同じ意味の2つの文章で見てみましょう。文章内の単語は違うもので構成したのですが類似している文章と判断されているのが類似度の数値の高さ(0.9309...)から見て取れますね!
result = sentence_similarity_w2v( "昔、高校の運動部で厳しい練習をしていた", "かなり前、学校の陸上部でハードなトレーニングをしていた" ) print(result)
ちなみに文章を扱う場合、Word2Vecを拡張したDoc2Vecというものもあるのでついでに使ってみます。
Doc2Vec
事前準備
SageMakerでノートブックインスタンスの作成
SageMakerの画面を開きます。
次にノートプックインスタンスを作成します。 下記の要領で赤枠の部分を対応して後はデフォルトのままで大丈夫です。
ノートブックはconda_python3の環境で実行します。
MeCabのインストール
本記事の上の方に記載しているものと同じなので、そちらをご覧ください。
モデルのダウンロード
ノートブックのセルに下記のコードをコピペして実行します。(結構時間がかかります。サイズも大きいのでご注意)
%%bash wget https://www.dropbox.com/s/njez3f1pjv9i9xj/jawiki.doc2vec.dmpv300d.tar.bz2?dl=0 mv jawiki.doc2vec.dmpv300d.tar.bz2?dl=0 jawiki.doc2vec.dmpv300d.tar.bz2 tar -jxvf jawiki.doc2vec.dmpv300d.tar.bz2
各種モジュールのインストール
本記事の上の方に記載しているものと同じなので、そちらをご覧ください。
モデルの読み込み
ノートブックのセルに下記のコードをコピペして実行します。
from gensim.models.doc2vec import Doc2Vec model_d2v = Doc2Vec.load("jawiki.doc2vec.dmpv300d.model")
関数
必要な処理を関数に定義しておきます。 下記、関数のコードもノートブックのセルにコピペして実行しておいてください。
import MeCab mecab = MeCab.Tagger("-Owakati -d /opt/mecab/lib/mecab/dic/neologd") def get_wakati(sentence): return mecab.parse(sentence).replace(' \n', '').split()
def sentence_similarity_d2v(sentence_1, sentence_2): w1 = get_wakati(sentence_1) w2 = get_wakati(sentence_2) return model_d2v.docvecs.similarity_unseen_docs(model_d2v, w1, w2)
文章の類似を判定してみよう
準備が整ったのでさっそく試しましょう。
result = sentence_similarity_d2v( "昔、高校の運動部で厳しい練習をしていた", "かなり前、学校の陸上部でハードなトレーニングをしていた" ) print(result)
数値が 1
に近いほど類似していることを表します。
こちらも文章内の単語は違うもので構成した2つの文章ですが、類似度は高い数値(0.843...)となっていますね!
ご注意
作業が終わったら余計な課金が発生しないよう、起動したノートブックインスタンスを停止(もしくは削除)しておいてください。
まとめ
今回扱ったWord2Vec、Doc2Vecは使用しているモデルの背景も異なるので単純に精度の比較はできないですが、双方とも文章の意味を捉えてるかのような結果を出せているのが良いですね。 新しい手法もまだまだ出ていますので、触ったらまた記事にしていきたいと思います。